/**
 * 文件名：@AbstractSoaClientFeignRegister.java <br/>
 * 包名：cn.efunbox.afw.soa.client.netflix.feign <br/>
 * 项目名：afw-soa-client <br/>
 * @author xtwin <br/>
 */
package cn.efunbox.afw.soa.client.netflix.feign;

import cn.efunbox.afw.soa.client.annotation.SoaClientConfig;
import cn.efunbox.afw.soa.client.register.AbstractSoaClientRegister;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.cloud.netflix.feign.FeignClientSpecification;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;

/**
 * 类名：AbstractSoaClientFeignRegister  <br />
 *
 * 功能：
 * 	由下面两个东东完成注册
 * 		org.springframework.cloud.netflix.feign.FeignClientSpecification
 * 		SoaClientFeignFactoryBean
 * 	
 *
 * @author xtwin <br />
 * 创建时间：2016年7月28日 上午10:09:17  <br />
 * @version 2016年7月28日
 */
public abstract class AbstractSoaClientFeignRegister extends AbstractSoaClientRegister implements EnvironmentAware {

	// 环境信息，由接口注入
	protected Environment environment;

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月28日 上午10:09:31<br/>
	 * 
	 * @param registry
	 * @param config
	 * @param client <br/>
	 * @see cn.efunbox.afw.soa.client.register.AbstractSoaClientRegister#doRegister(org.springframework.beans.factory.support.BeanDefinitionRegistry, cn.efunbox.afw.soa.client.annotation.SoaClientConfig, org.springframework.beans.factory.config.BeanDefinition)
	 */
	@Override
	protected void doRegister(BeanDefinitionRegistry registry, SoaClientConfig config, BeanDefinition client) {
		// 注册配置
		registerConfiguration(registry, config, client);
		// 注册客户端
		registerClient(registry, config, client);
	}
	
	/**
	 * 功能：注册配置信息 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2016年7月25日 上午11:15:47 <br/>
	 */
	protected void registerConfiguration(BeanDefinitionRegistry registry, SoaClientConfig soaServiceClient, BeanDefinition client) {
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
		builder.addConstructorArgValue(getConfigName(soaServiceClient));
		builder.addConstructorArgValue(soaServiceClient.configurations());
		registry.registerBeanDefinition(getConfigName(soaServiceClient) + "." + FeignClientSpecification.class.getSimpleName(), builder.getBeanDefinition());
	}
	
	/**
	 * 功能：注册client <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2016年7月25日 上午11:19:19 <br/>
	 */
	protected void registerClient(BeanDefinitionRegistry registry, SoaClientConfig config, BeanDefinition client) {
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SoaClientFeignFactoryBean.class);
		
		builder.addPropertyValue("url", environment.resolvePlaceholders(config.url()));
		builder.addPropertyValue("path", environment.resolvePlaceholders(config.path()));
		builder.addPropertyValue("configName", getConfigName(config));
		builder.addPropertyValue("name", environment.resolvePlaceholders(config.service()));
		builder.addPropertyValue("type", client.getBeanClassName());
		builder.addPropertyValue("decode404", false);
		builder.addPropertyValue("fallback", void.class);
		builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);

		AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
		beanDefinition.setPrimary(true);
		//beanDefinition.setLazyInit(true); // 延迟初始化
		BeanDefinitionReaderUtils.registerBeanDefinition(
				new BeanDefinitionHolder(
						beanDefinition, 
						client.getBeanClassName(), 
						new String[] { config.service() + "SoaClientFeign" }
				)
				, registry);
	}
	
	/**
	 * 功能：获取配置定义名称 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2016年7月25日 上午11:16:41 <br/>
	 */
	protected String getConfigName(SoaClientConfig soaServiceClient) {
		return "SOA_SERVICIE:" + environment.resolvePlaceholders(soaServiceClient.service());
	}
	
	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月28日 上午10:12:43<br/>
	 * 
	 * @param environment <br/>
	 * @see org.springframework.context.EnvironmentAware#setEnvironment(org.springframework.core.env.Environment)
	 */
	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
	}
}
